package com.ch4;

import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

/**
 * @author woldier
 * @version 1.0
 * @description 保护性暂停
 * @date 2023/5/5 14:19
 **/
@Slf4j(topic = "c.Thread")
public class Demo08 {
    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new People().start();
        }
        MailBox.getKeys().forEach( e -> {
            new Postman(e,"邮件"+e).start();
        });
    }
}


@Slf4j(topic = "c.Thread")
class People extends Thread{
    /**
    *
    * description 收件人
    *
    *
    * @return void
    * @author: woldier
    * @date: 2023/5/6 14:23
    */
    @Override
    public void run() {
        /*得到一个对象GuardedObject3*/
        GuardedObject3 guardedObject3 = MailBox.createGuardedObject3();
        /*取信*/
        Object response = guardedObject3.getResponse();
        log.debug("message : {}",response.toString());
    }
}

@Slf4j(topic = "c.Thread")
class Postman extends Thread {

    private final long id;
    private final String msg;

    public Postman(long id, String msg) {
        this.id = id;
        this.msg = msg;
    }

    /***
    *
    * description 送件人
    *
    *
    * @return void
    * @author: woldier
    * @date: 2023/5/6 14:27
    */
    @Override
    public void run() {
        GuardedObject3 guardedObject3 = MailBox.getGuardedObject3(id);
        log.debug("送信");
        guardedObject3.complete(msg);
    }
}

@Slf4j(topic = "c.Thread")
class MailBox {
    private static Map<Long, GuardedObject3> box = new Hashtable<>();
    private static Long id = 0L;

    public synchronized static Long generateId() {
        return id++;
    }

    public static GuardedObject3 createGuardedObject3() {
        GuardedObject3 guardedObject3 = new GuardedObject3(generateId());
        box.put(guardedObject3.getId(), guardedObject3);
        return guardedObject3;
    }

    public static GuardedObject3 getGuardedObject3(Long id) {
        return box.remove(id);
    }

    public static Set<Long> getKeys() {
        return box.keySet();
    }
}

@Slf4j(topic = "c.Thread")
class GuardedObject3 {
    private long id;


    private Object response;

    public GuardedObject3(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    /**
     * description 同步性线程 消费者 加入超时时间
     *
     * @return java.lang.Object
     * @author: woldier
     * @date: 2023/5/5 8:55
     */
    public synchronized Object getResponse(long timeout) {
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime pass = start;
        int waitTime = (start.plusSeconds(timeout).toLocalTime().toSecondOfDay() - pass.toLocalTime().toSecondOfDay()) * 1000;
        while (response == null) {
            if (start.plusSeconds(timeout).isBefore(pass)) {
                break;
            }
            log.debug("消费者等待生产者");
            try {

                this.wait(waitTime);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            pass = LocalDateTime.now();
        }
        log.debug("消费者跳出消费等待");
        return response;
    }

    /**
     * description 同步性线程 消费者 默认超时时间 6000 ms
     *
     * @return java.lang.Object
     * @author: woldier
     * @date: 2023/5/5 13:11
     */
    public synchronized Object getResponse() {
        return getResponse(6);
    }


    /**
     * description 同步线程 生产者
     *
     * @param o 生产者产生的结果
     * @return void
     * @author: woldier
     * @date: 2023/5/5 8:56
     */
    public synchronized void complete(Object o) {
        response = o;
        this.notifyAll();
        log.debug("生产者");
    }
}
